﻿using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.Domain.Repositories;
using Abp.Linq.Extensions;
using Abp.Runtime.Session;
using Abp.UI;
using SingleUserMall.Authorization.Users;
using SingleUserMall.Common;
using SingleUserMall.Items;
using SingleUserMall.Mall.Form;
using SingleUserMall.Mall.VO;
using SingleUserMall.Stores;
using SingleUserMall.Stores.VO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SingleUserMall.StoreSettings;
using SingleUserMall.StoreSettings.VO;
using SingleUserMall.Points;
using Abp.AutoMapper;
using SingleUserMall.Actives;
using System.Data.Entity;
using Abp.Domain.Uow;

namespace SingleUserMall.Mall
{
    public class MallAppService : SingleUserMallAppServiceBase, IMallAppService
    {
        private readonly IRepository<Banner, long> _bannerRepository;
        private readonly IRepository<ItemCategory, long> _itemCategoryRepository;
        private readonly IRepository<Item, long> _itemRepository;
        private readonly IRepository<RecommendCategory, long> _recommendCategoryRepository;
        private readonly IRepository<Store> _storeRepository;
        private readonly IRepository<UserStoreFavorite, long> _userFavoriteStoreRepository;
        private readonly IRepository<HomeSetting, long> _homeSettingRepository;
        private readonly IRepository<PointRules, long> _pointRulesRepository;
        private readonly IRepository<Active, long> _activeRepository;
        private readonly IRepository<ActiveRecord, long> _activeRecordRepository;
        private readonly IRepository<UserPoints, long> _userPointsRepository;
        public MallAppService(
            IRepository<Banner, long> bannerRepository,
            IRepository<ItemCategory, long> itemCategoryRepository,
            IRepository<Item, long> itemRepository,
            IRepository<RecommendCategory, long> recommendCategoryRepository,
            IRepository<Store> storeRepository,
            IRepository<UserStoreFavorite, long> userFavoriteStoreRepository,
            IRepository<HomeSetting, long> homeSettingRepository,
            IRepository<PointRules, long> pointRulesRepository,
            IRepository<Active, long> activeRepository,
            IRepository<ActiveRecord, long> activeRecordRepository,
            IRepository<UserPoints, long> userPointsRepository
            )
        {
            _bannerRepository = bannerRepository;
            _itemCategoryRepository = itemCategoryRepository;
            _itemRepository = itemRepository;
            _recommendCategoryRepository = recommendCategoryRepository;
            _storeRepository = storeRepository;
            _userFavoriteStoreRepository = userFavoriteStoreRepository;
            _homeSettingRepository = homeSettingRepository;
            _pointRulesRepository = pointRulesRepository;
            _activeRepository = activeRepository;
            _activeRecordRepository = activeRecordRepository;
            _userPointsRepository = userPointsRepository;
        }
        public async Task<HomeVO> GetHomeAsync(HasStoreForm form)
        {
            try
            {
                var banners = _bannerRepository.GetAll().Where(x => x.Enabled && x.StoreId == form.StoreId)
                    .OrderBy(x => x.Sort);
                var itemCategories = _itemCategoryRepository.GetAll().Where(x => x.Enabled && x.ParentId == null)
                    .Where(x => x.StoreId == form.StoreId)
                    .OrderBy(x => x.Sort);
                //var hotItems = items.Where(x => x.IsHot)
                //    .OrderByDescending(x => x.MonthSale)
                //    .ThenByDescending(x => x.CreationTime).Take(6);
                //var recommentdCategories = _recommendCategoryRepository.GetAll().Where(x => x.Enabled && x.StoreId == form.StoreId )
                //    .OrderBy(x => x.Sort).Take(6);
                //var homeItems = _itemRepository.GetAll().Where(x => x.IsSale && !x.IsGroup && !x.IsTimeLimit)
                //    .WhereIf(form.StoreId != 1, x => x.StoreId == form.StoreId)
                //    .OrderBy(x=>x.Sort)
                //    .ThenByDescending(x => x.MonthSale)
                //    .ThenByDescending(x => x.CreationTime)
                //    .Take(8);
                var store = _storeRepository.FirstOrDefault(x => x.Id == form.StoreId);
                if(store!= null && store.IsInvalid)
                {
                    throw new UserFriendlyException("该店铺已经被关停");
                }
                List<Store> stores = new List<Store>();
                if (form.StoreId == 1)
                {
                    stores = _storeRepository.GetAll().Where(x => x.Id == 2 || x.Id == 3 || x.Id == 4 || x.Id == 66 || x.Id==181).ToList();
                }

                var homeSetting = _homeSettingRepository.GetAll().OrderByDescending(x=> x.CreationTime).FirstOrDefault();
                var result = new HomeVO
                {
                    HomeSetting = homeSetting.ToVO<HomeSetting, HomeSettingVO>(),
                    UpBanners = banners.Where(x => x.BannerLocation == BannerLocation.Up).ToListVO<Banner, BannerMiniVO>(),
                    MiddleBanners = banners.Where(x => x.BannerLocation == BannerLocation.Middle).ToListVO<Banner, BannerMiniVO>(),
                    LimitBanner = banners.Where(x => x.BannerLocation == BannerLocation.TimeLimit).OrderByDescending(x => x.CreationTime).FirstOrDefault().ToVO<Banner, BannerMiniVO>(),
                    GroupBanner = banners.Where(x => x.BannerLocation == BannerLocation.Group).OrderByDescending(x => x.CreationTime).FirstOrDefault().ToVO<Banner, BannerMiniVO>(),
                    GoodBanner = banners.Where(x => x.BannerLocation == BannerLocation.Good).OrderByDescending(x => x.CreationTime).FirstOrDefault().ToVO<Banner, BannerMiniVO>(),
                    PFIcon = banners.Where(x => x.BannerLocation == BannerLocation.PF).OrderByDescending(x => x.CreationTime).FirstOrDefault().ToVO<Banner, BannerMiniVO>(),
                    DLIcon = banners.Where(x => x.BannerLocation == BannerLocation.DL).OrderByDescending(x => x.CreationTime).FirstOrDefault().ToVO<Banner, BannerMiniVO>(),
                    ZJIcon = banners.Where(x => x.BannerLocation == BannerLocation.ZJ).OrderByDescending(x => x.CreationTime).FirstOrDefault().ToVO<Banner, BannerMiniVO>(),
                    NFIcon = banners.Where(x => x.BannerLocation == BannerLocation.NF).OrderByDescending(x => x.CreationTime).FirstOrDefault().ToVO<Banner, BannerMiniVO>(),
                    ZQIcon = banners.Where(x => x.BannerLocation == BannerLocation.ZQ).OrderByDescending(x => x.CreationTime).FirstOrDefault().ToVO<Banner, BannerMiniVO>(),
                    JFSCIcon = banners.Where(x => x.BannerLocation == BannerLocation.JFSC).OrderByDescending(x => x.CreationTime).FirstOrDefault().ToVO<Banner, BannerMiniVO>(),
                    DLSCIcon = banners.Where(x => x.BannerLocation == BannerLocation.DLSC).OrderByDescending(x => x.CreationTime).FirstOrDefault().ToVO<Banner, BannerMiniVO>(),
                    XYKIcon = banners.Where(x => x.BannerLocation == BannerLocation.XYK).OrderByDescending(x => x.CreationTime).FirstOrDefault().ToVO<Banner, BannerMiniVO>(),
                    DLSM = banners.Where(x => x.BannerLocation == BannerLocation.DLSM).OrderByDescending(x => x.CreationTime).FirstOrDefault().ToVO<Banner, BannerMiniVO>(),
                    ItemCategories = itemCategories.ToListVO<ItemCategory, ItemCategoryMiniVO>(),
                    //HotItems = hotItems.ToListVO<Item, ItemMiniVO>(),
                    //RecommendCategories = recommentdCategories.ToListVO<RecommendCategory, RecommendCategoryMiniVO>((c, vo) =>
                    //{
                    //    vo.Items = items.Where(x => x.RecommendCategoryId == c.Id && !x.IsTimeLimit && !x.IsGroup)
                    //    .OrderBy(x => x.Sort)
                    //    .ThenByDescending(x => x.MonthSale)
                    //    .ThenByDescending(x => x.CreationTime)
                    //    .Take(10)
                    //    .ToListVO<Item, ItemMiniVO>();
                    //}),
                    //Items = homeItems.ToListVO<Item, ItemMiniVO>(),
                    store = store.ToVO<Store, StoreViewVO>((s, vo) =>
                    {
                        if (AbpSession.UserId == null)
                        {
                            vo.IsFavorite = false;
                        }
                        else
                        {
                            var userId = AbpSession.GetUserId();
                            vo.IsFavorite = _userFavoriteStoreRepository.Count(x => x.FavoriteUserId == userId && x.StoreId == s.Id) > 0;
                        }
                        vo.CommentRate = s.StoreStar * 20 + "%";
                    }),
                    stores = stores.ToListVO<Store,StoreMiniViewVO>()
                };
                return await Task.FromResult(result);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public async Task<ListResultDto<RecommendCategoryMiniVO>> GetRecommendCategoriesByStoreId(SingleId<long> form)
        {
            var recommentdCategories = _recommendCategoryRepository.GetAll().Where(x => x.Enabled && x.StoreId == form.Id).OrderBy(x => x.Sort);
            return await recommentdCategories.ToListResultDtoAsync<RecommendCategory, RecommendCategoryMiniVO>();
        }

        public async Task<PagedResultDto<ItemMiniVO>> GetItemsByRecommendId(RecommendForm form)
        {
            var items = _itemRepository.GetAll().Where(x => x.IsSale && x.RecommendCategoryId == form.RecommendId).OrderBy(x => x.Sort)
                        .ThenByDescending(x => x.MonthSale)
                        .ThenByDescending(x => x.CreationTime);
            return await items.ToPagedResultDtoAsync<Item, ItemMiniVO>(form);
        }

        public async Task<PagedResultDto<ItemMiniVO>> SearchItemsAsync(ItemSearchForm form)
        {
            var query = _itemRepository.GetAll().Where(x => x.StoreId == form.StoreId && x.IsSale)
                .WhereIf(!string.IsNullOrEmpty(form.Keywords), x => x.Name.Contains(form.Keywords) || x.Tags.Contains(form.Keywords))
                .OrderByDescending(x => x.IsHot)
                .ThenBy(x => x.Sort)
                .ThenByDescending(x => x.MonthSale)
                .ThenByDescending(x => x.CreationTime);
            return await query.ToPagedResultDtoAsync<Item, ItemMiniVO>(form);
        }

        [AbpAuthorize]
        public async Task<ListResultDto<BannerMiniVO>> GetEWM()
        {
            var banners = _bannerRepository.GetAll().Where(x => x.BannerLocation == BannerLocation.EWM && x.StoreId==1);
            return await banners.ToListResultDtoAsync<Banner, BannerMiniVO>();
        }

        [AbpAuthorize]
        public async Task<ListResultDto<ActiveAPPVO>> GetActivesByUser()
        {
            var userId = AbpSession.GetUserId();
            var user = await UserManager.GetUserByIdAsync(userId);
            var yesterday = DateTime.Now.AddDays(-1);
            var deleteQuery = _activeRecordRepository.GetAll().Where(x => x.UserId == userId && x.User.IsVip && x.User.VipLevel
             == 2 && x.ActiveId == 2 && DbFunctions.TruncateTime(x.CreationTime) == DbFunctions.TruncateTime(yesterday)).ToList();
            deleteQuery.ForEach(x =>
            {
                _activeRecordRepository.Delete(x);
            });
            var deleteQueryShare = _activeRecordRepository.GetAll().Where(x => x.UserId == userId && x.ActiveId == 1 && DbFunctions.TruncateTime(x.CreationTime) == DbFunctions.TruncateTime(yesterday)).ToList();
            deleteQueryShare.ForEach(x =>
            {
                _activeRecordRepository.Delete(x);
            });
            CurrentUnitOfWork.SaveChanges();
            var query = _activeRepository.GetAll().Where(x=> x.Enabled).OrderBy(x => x.Sort);
            return await query.ToListResultDtoAsync<Active, ActiveAPPVO>((v,vo)=>
            {
                var activeRecord = _activeRecordRepository.FirstOrDefault(x => x.UserId == userId && x.ActiveId == v.Id);
                vo.QueryTimes = activeRecord?.QueryTimes ?? 0;
                using (CurrentUnitOfWork.DisableFilter(AbpDataFilters.SoftDelete))
                {
                    var count = _activeRecordRepository.GetAll().Where(x => x.UserId == userId && x.ActiveId == v.Id).Sum(x => (int?)x.QueryTimes);
                    if (count != null)
                    {
                        vo.TotalQueryTimes = count.Value;
                    }
                }

                vo.VipLevel = user.VipLevel;
                vo.IsVip = user.IsVip;
                vo.IsFinish = activeRecord?.IsFinish ?? false;
            });
        }

        [AbpAuthorize]
        public async Task<ListResultDto<ActiveAPPVO>> FinishActive(SingleId<long> form)
        {
            var userId = AbpSession.GetUserId();
            var user = await UserManager.GetUserByIdAsync(userId);
            var active = _activeRepository.FirstOrDefault(form.Id);
            using (CurrentUnitOfWork.DisableFilter(AbpDataFilters.SoftDelete))
            {
                var count = _activeRecordRepository.Count(x => x.ActiveId == form.Id && x.UserId == userId && x.IsFinish);
                if (user.IsVip && user.VipLevel == 1 && active.Id == 2 && count > 1)
                {
                    throw new UserFriendlyException("请升级到合伙人再领取奖励 在首页购买果树可升级到合伙人");
                }
            }
            var userActiveRecord = _activeRecordRepository.FirstOrDefault(x => x.ActiveId == form.Id && x.UserId == userId);
            userActiveRecord.IsFinish = true;
            _userPointsRepository.Insert(new UserPoints
            {
                UserId = userId,
                Title = $"{active.Name}获得{active.Amount}元体验金",
                Points = active.Amount,
                Type = UserPointsType.TYJ,
                Status = UserPointsStatus.In,
                FromUserId = userId,
            });
            user.Points += active.Amount;
            if(user.SourceUserId.HasValue)
            {
                var sourceUser = await UserManager.GetUserByIdAsync(user.SourceUserId.Value);
                if (sourceUser != null)
                {
                    OrderManager.CalculateSignOrActivePoint(user, active.Amount, active.Name, sourceUser);
                }
            }
            CurrentUnitOfWork.SaveChanges();
            var query = _activeRepository.GetAll().OrderBy(x => x.Sort);
            return await query.ToListResultDtoAsync<Active, ActiveAPPVO>((v, vo) =>
            {
                var activeRecord = _activeRecordRepository.FirstOrDefault(x => x.UserId == userId && x.ActiveId == v.Id);
                vo.IsVip = user.IsVip;
                vo.VipLevel = user.VipLevel;
                vo.QueryTimes = activeRecord?.QueryTimes ?? 0;
                vo.IsFinish = activeRecord?.IsFinish ?? false;
            });
        }


    }
}
